package org.qianji.goosql.dql.clause;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.qianji.goosql.cond.Condition;
import org.qianji.goosql.dql.Join;
import org.qianji.goosql.table.Table;

/**
 * 关联From子句。
 * 
 * @author gmz
 * 
 */
public class JoinedFrom extends AbstractFrom {

	/**
	 * 
	 */
	private static final long serialVersionUID = -2264910215756557287L;

	private From from;
	private Join join;
	private Table table;
	private Condition cond;

	/**
	 * 根据From子句、关联类型、表、关联条件构造关联From子句。
	 * 
	 * @param from
	 *            {@link From} From子句
	 * @param join
	 *            {@link Join} 关联类型
	 * @param table
	 *            {@link Table} 表
	 * @param cond
	 *            {@link Condition} 关联条件
	 */
	public JoinedFrom(From from, Join join, Table table, Condition cond) {
		super();
		if (from == null || join == null || table == null) {
			throw new NullPointerException("args form/join/table can't be null");
		}
		this.from = from;
		this.join = join;
		this.table = table;
		this.cond = cond;
	}

	/**
	 * 获取From子句。
	 * 
	 * @return {@link From} From子句
	 */
	public From getFrom() {
		return from;
	}

	/**
	 * 获取关联类型。
	 * 
	 * @return {@link Join} 关联类型
	 */
	public Join getJoin() {
		return join;
	}

	/**
	 * 获取表。
	 * 
	 * @return {@link Table} 表
	 */
	public Table getTable() {
		return table;
	}

	/**
	 * 获取关联条件。
	 * 
	 * @return {@link Condition} 关联条件
	 */
	public Condition getCond() {
		return cond;
	}

	@Override
	public String toSql() {
		StringBuffer frm = new StringBuffer(from.toSql()).append(" ").append(join).append(" ").append(table.toSql());
		if (cond != null) {
			frm.append(" ON ").append(cond.toSql());
		}
		return frm.toString();
	}

	@Override
	public List<Object> getPlacedParameters() {
		List<Object> ppl = new ArrayList<Object>();
		ppl.addAll(from.getPlacedParameters());
		ppl.addAll(table.getPlacedParameters());
		if (cond != null) {
			ppl.addAll(cond.getPlacedParameters());
		}
		return ppl;
	}

	@Override
	public Map<String, Object> getNamedParameters() {
		Map<String, Object> npm = new HashMap<String, Object>();
		npm.putAll(from.getNamedParameters());
		npm.putAll(table.getNamedParameters());
		if (cond != null) {
			npm.putAll(cond.getNamedParameters());
		}
		return npm;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null || !(obj instanceof JoinedFrom)) {
			return false;
		}
		JoinedFrom other = (JoinedFrom) obj;
		if (from.equals(other.getFrom()) && join.equals(other.getJoin()) && table.equals(other.getTable())
				&& ((cond == null && other.getCond() == null) || cond.equals(other.getCond()))) {
			return true;
		}
		return false;
	}

	@Override
	public int hashCode() {
		int hc = 37 * 17 + from.hashCode();
		hc = 37 * hc + join.hashCode();
		hc = 37 * hc + table.hashCode();
		if (cond != null) {
			hc = 37 * hc + cond.hashCode();
		}
		return hc;
	}

	@Override
	public String toString() {
		return toSql();
	}

}
